//
//  SocketManager.swift
//  cangchu
//
//  Created by kang on 2021/11/29.
//

import Foundation
import Starscream

public enum SocketStatus{
    case noConn//未连接
    case connSuccess//连接成功
    case connError(reson:String,code:Int)//连接失败
}

public protocol SocketCallBack{
    func connect(status:SocketStatus)
    func messsage(content:String)
}

public class SocketClient: WebSocketDelegate{
    
    var socket:WebSocket?
    var callback:SocketCallBack?
    var status:SocketStatus = .noConn
    var url:String?
    
    public func connect(url:String) throws{
        
        self.url = url
        if url.isEmpty{
            Logger.log(message: "url is empty")
            throw SocketError.PARAMS_ERROR(message: "url is empty")
        }
        
        Logger.log(message: "connect ...")
        var request = URLRequest(url: URL(string: url)!)
        request.timeoutInterval = 5
        socket = WebSocket(request: request)
        socket?.delegate = self
        socket?.connect()
    }
    
    public func handlerError(error:Error){
        print("socket error:\(error.localizedDescription)")
    }
    
    public func reConnect(){
        Logger.log(message: "reconnect ...")
        socket?.connect()
    }
    
    public func disconnect(){
        Logger.log(message: "disconnect ...")
        socket?.disconnect()
    }
    
    public func send(content:String,completion:@escaping (()->())){
        Logger.log(message: "send message \(content)")
        socket?.write(string: content, completion: completion)
    }
    
    public func destory(){
        Logger.log(message: "destroy ...")
        socket?.disconnect()
        socket = nil
    }
    
    public func didReceive(event: WebSocketEvent, client: WebSocket) {
        
        switch event {
        case .connected(_):
            self.status = .connSuccess
            callback?.connect(status: .connSuccess)
            break
        case .disconnected(let reason, let code):
            self.status = .connError(reson: reason, code: Int(code))
            callback?.connect(status: .connError(reson: reason, code: Int(code)))
            break
        case .text(let string):
            callback?.messsage(content: string)
            break
        case .binary(_):
            break
        case .ping(_):
            break
        case .pong(_):
            break
        case .viabilityChanged(_):
            break
        case .reconnectSuggested(_):
            break
        case .cancelled:
            self.status = .noConn
            break
        case .error(let error):
            self.status = .connError(reson: error?.localizedDescription ?? "", code: -1)
            callback?.connect(status: .connError(reson: error?.localizedDescription ?? "", code: -1))
        }
    }
}
